Google Apps Script から AWS SDK for JavaScript を使って、スプレッドシートのデータを S3 にアップロードしてみた
はじめに
社内で利用するシステムを作成するにあたり、Google スプレッドシートにあるデータを CSV 形式に変換して S3 にアップロードする処理の作成を依頼されたため、 タイトルにある Google Apps Script から AWS SDK for JavaScript を使って S3 にデータをアップロードしてみました。 なお前提として筆者は、Google Apps Script も JavaScript も初心者であるため、掲載されたコードにいけてない部分があったとしてもご容赦ください。 拙いソースコードではありますが、どこかで同じように困っている誰かの役に立てれば幸いです。
前提条件
- 特定のスプレッドシートでしか利用しないため、Google Apps Script は Container-bound とする
- Google スプレッドシートへのアクセスに既に認証機構があるため、スクリプト側では "accessKeyId" および "secretAccessKey" をハードコーディングしている
- オブジェクトをアップロードする S3 Bucket に対して CORS の設定が行われていること(参考情報:ブラウザの JavaScript)
- 指定バケットへオブジェクトアップロード権限が与えられた IAM ユーザーの「アクセスキーID」と「シークレットアクセスキー」を取得済みであること
- 同僚から教えて貰った GitHub の情報 (Cannot load SDK into Google Apps Script · Issue #620 · aws/aws-sdk-js)を参考とした
実装
- 以下、コード.gs のソースコードを示します。
var app = SpreadsheetApp; function onOpen(e){ showContentApp(); } function showContentApp(){ var html = HtmlService.createHtmlOutputFromFile('sample').setWidth(100).setHeight(100); app.getActiveSpreadsheet().show(html); } function getSpreadsheetData(){ // スクリプトが紐付いているスプレッドシートの参照を取得 var ss = SpreadsheetApp.getActiveSpreadsheet(); // スクリプト実行時にアクティブなシートの参照を取得 var sheet = ss.getActiveSheet(); // データを取得 getRange(行番号,列番号,範囲の行数,列数) A1:B3000 var data = sheet.getRange(1,1,3000,2).getValues(); return data; }
onOpen() が呼ばれると、showContentApp() 内で、sample.html が読み込まれ以下のイメージにある Upload S3 ボタンが含まれたウィンドウが表示されます。 getSpreadsheetData() は、sample.html 内から呼ばれる関数でありコメントに記載のとおり A1 から B3000 までのセルの範囲に含まれるデータ(Array の2次元配列)が返ります。
入力データは、イメージ内に表示されているとおり "ID" と "メールアドレス" です。
- 以下、sample.html のソースコードを示します。
<script src="https://sdk.amazonaws.com/js/aws-sdk-2.122.0.min.js"></script> <script src="https://code.jquery.com/jquery-3.2.1.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script> <script type="text/javascript">//<![CDATA[ $(function() { $("#btn").on('click', function() { AWS.config.region = 'ap-northeast-1'; AWS.config.maxRetries = 3; AWS.config.update({ accessKeyId: 'ID', secretAccessKey: 'KEY' }); // Create S3 object var s3 = new AWS.S3(); // getSpreadsheetData SuccessHandler function onSuccess(body){ if( !body ) return; var csv = ''; var count = body.length; // convert Array object to string (CSV format) for(var i=0;i<count;i++){ csv += '"' + body[i].join('","') + '"\n'; } // Create S3 putObject params var params = { Bucket: 'test', Key: "test.csv", Body: csv }; s3.putObject(params, function(err, data) { if(err) { console.dir(err); console.log('Request ID:', data.RequestId); $("#status").html("Error"); } $("#status").html("Success"); }); } // End of onSuccess() // getSpreadsheetData FailureHandler function onFailure(e){ console.log(e, 'getSpreadsheetData()'); } // End of onFailure() // execute getSpreadsheetData function in コード.gs google.script.run.withSuccessHandler(onSuccess).withFailureHandler(onFailure).getSpreadsheetData(); }); }); //]]></script> <button id="btn">Upload S3</button> <p></p> <div id="status"></div>
HTML 内で、AWS SDK for JavaScript(aws-sdk-2.122.0.min.js)を読み込んでいます。 ウィンドウ内の Upload S3 ボタンをクリックすると S3 オブジェクトが作成されます。次にコード.gs 内の getSpreadsheetData() が非同期で呼び出され 関数の処理が成功しデータが返ってきた場合、onSuccess() が実行されます。スプレッドシートの行数回だけデータを展開し、CSV のフォーマットに変換した String を組み立てます。 データが作成されたら S3 の putObject() を呼び出し CSV データを送信します。処理が成功すれば、ボタン下に "Success" を表示します。
S3 に転送された CSV データは、以下のとおりです。
"id1","[email protected]" "id2","[email protected]" "id3","[email protected]" "id4","[email protected]" "id5","[email protected]" "id6","[email protected]"
期待した通りに CSV データが、S3 へアップロードされました。
さいごに
「はじめに」でもお伝えしましたが、筆者は、Google Apps Script も JavaScript も初心者です。 Google Apps Script は人生初のコーディングで、JavaScript は少し触ったことがある程度です。 掲載しているコードは、まだまだ改善の余地があることは重々承知の上で、思い切って公開してみました。 繰り返しとなりますが、どこかで同じように困っている誰かの役に立てれば幸いです。
参考情報
- Class: AWS.S3 — AWS SDK for JavaScript
- Container-bound Scripts | Apps Script | Google Developers
- Class google.script.run (Client-side API) | Apps Script | Google Developers
- Libraries | Apps Script | Google Developers
- [Google Apps Script]スプレッドシート上にウィンドウを表示する | 初心者備忘録 #HTML ファイルを読み込み、ウィンドウを表示する部分のコードを参考にさせて頂きました。
ではでは